Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows & X11: Window::set_resizable #558

Merged
merged 9 commits into from
Jun 11, 2018

Conversation

dannyfritz
Copy link
Contributor

@dannyfritz dannyfritz commented Jun 7, 2018

  • Tested on all platforms changed (Mutter, Windows 10)
  • Added an entry to CHANGELOG.md if knowledge of this change could be valuable to users
  • Updated documentation to reflect any user-facing changes, including notes of platform-specific behavior
  • Created an example program if it would help users understand this functionality

Related to #540

@francesca64
Copy link
Member

More architecting might be in order for this PR. Currently, the max and min resize dimensions are lost when toggling resizable and not.

Gah, I was looking forward to nagging you about needing to handle that, but it seems you already knew. The line I'd prepared was about how the fact that this sets the min/max size should be an implementation detail that's encapsulated by the API.

That state should be stored in SharedState, and it's of the utmost importance that I remember to DPI-adjust all of this when I rebase #548.

I did expose the method through the wrapper Window class

If I were you, I'd do all of this in one PR, or just take the approach I used in #553 and don't add the top-level Window method yet. Android, iOS, and Emscripten are just supposed to have "N/A" stubs, so getting CI to pass is easy, though any platforms where it is applicable should have unimplemented! stubs instead.

Since this seems to be mostly complete, I'm not against including it in 0.15.1, though it also doesn't really matter, since 0.16.0 will be released quite soon afterwards (I just want to get some regression fixes out instead of gating them behind an API migration).

CHANGELOG.md Outdated
@@ -3,6 +3,7 @@
- On X11, the `Moved` event is no longer sent when the window is resized without changing position.
- `MouseCursor` and `CursorState` now implement `Default`.
- `WindowBuilder::with_resizable` implemented for Windows, X11, and macOS.
- `Window::set_resizable` implemented for MacOS, X11, and Windows.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The correct stylization is "macOS", and it also reads a little easier if you use the same ordering as in the previous line.

}
_ => winit::ControlFlow::Continue,
},
_ => winit::ControlFlow::Continue,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an official winit example™, it would be good if you refactored this to not repeat winit::ControlFlow::Continue, i.e. https://github.com/tomaka/winit/blob/master/examples/handling_close.rs

src/lib.rs Outdated
@@ -422,7 +422,7 @@ pub struct WindowAttributes {
/// The default is `None`.
pub max_dimensions: Option<(u32, u32)>,

/// [Windows & X11 only] Whether the window is resizable or not
/// [Windows, MacOS, and X11 only] Whether the window is resizable or not
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you followed the precedent set by [iOS only], but you should know two things about that:

  1. The [iOS only] doc comment isn't accurate anymore...
  2. That was added a long time ago, and back before winit had someone barking about style, so it's not necessarily something you should replicate. Sticking to the conventions established in other areas of the documentation is probably better.

match self {
&Window::X(ref w) => w.set_resizable(resizable),
// &Window::Wayland(ref w) => w.set_resizable(resizable),
_ => {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We tend to favor _ => (), but more importantly, it's more appropriate to stub this as unimplemented!(), by decree of tomaka.

The idea is that it makes people more likely to fix it... in my experience, all it does is make people more likely to yell at us, though that does make me more likely to fix it.

Copy link
Contributor

@elinorbgr elinorbgr Jun 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've released version 0.2.2 of smithay-client-toolkit which adds a set_resizable method to its Window type, that does what we need for wayland support. So, fixing should be pretty trivial, I can do this once this is merged, as soon as I secure the 5 minutes it'll take.

unsafe {
self.update_normal_hints(|size_hints| {
if resizable {
(*size_hints).flags &= !ffi::PMinSize;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can cut the number of flag changes in half in this function.

winuser::GetWindowLongW(self.window.0, winuser::GWL_STYLE)
};
if resizable {
style |= winuser::WS_SIZEBOX as i32;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer you use the winapi LONG type instead of i32.

if resizable {
style |= winuser::WS_SIZEBOX as i32;
} else {
style &= !winuser::WS_SIZEBOX as i32;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the precedence here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The precedence for removing the WS_SIZEBOX when setting resizable to false? I guess I'm not 100% sure what you are referring to.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh lol. The precedence is LONG.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I just wanted to make sure it was zero-extending before flipping the bits. Or rather, I wanted to make sure you thought about that.

@@ -239,6 +239,33 @@ impl Window {
}
}
}

/// See the docs in the crate root file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to add this comment, since #548 completely removes them... they don't seem to be at all helpful, especially since these are doc comments on private methods.

More importantly, what happens when you use this method while the window is fullscreen?

@dannyfritz dannyfritz changed the title X11: Window::set_resizable Windows & X11: Window::set_resizable Jun 8, 2018
@dannyfritz dannyfritz mentioned this pull request Jun 8, 2018
4 tasks
@dannyfritz
Copy link
Contributor Author

I addressed style changes and X11 remembering the window min/max size. I haven't addressed or tested setting resizable while in fullscreen.

src/window.rs Outdated
/// ## Platform-specific
///
/// This only has an effect on Windows, X11, and macOS.
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You left the block comment open/close in.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, good catch. I'm not sure I would have ever seen that as a code reviewer.

@francesca64
Copy link
Member

For whatever reason, set_resizable(true) doesn't work on Xfwm4. The hints show up as expected in xprop, and it worked when I tried it in KWin and Openbox... I'll see if I can figure out a workaround, but I'll merge this even if I can't find a solution. There are some things that are simply beyond our power.

@francesca64
Copy link
Member

francesca64 commented Jun 9, 2018

This description doesn't seem entirely accurate; from what I'm seeing Xfwm stops picking up on changes whenever min/max are set to values that make it unresizable (even when after mapping): https://mail.xfce.org/pipermail/xfce/2015-August/034641.html

Note that my phrasing of "values that make it unresizable" rather than "the same value" was deliberate; I tried to outsmart it by adding 1 to the min size and subtracting 1 from the max size, but the problem was still present. (It would've been a bad hack to use anyway, since I'm sure there are some things that become quite unhappy if min>max.)

So, once logging is added, I'll just add a warn! if it's being used on Xfwm4. Besides that, I just need to check that this works as expected on Windows, and we'll be good to go.

@francesca64
Copy link
Member

As predicted, things on Windows don't quite work right with fullscreen mode. Creating a window with_resizable(false), and then calling set_resizable(true) after entering fullscreen results in the following:

  1. The window is "snapped out" of fullscreen, but still approximately the fullscreen size
  2. The window is, at that point, resizable
  3. Exiting fullscreen restores the original size, but the window isn't resizable
  4. Calling set_resizable(true) again does not make the window resizable
  5. It can only be made resizable again by calling set_resizable(false) before calling set_resizable(true)

There don't seem to be any other problems, though.

@francesca64
Copy link
Member

So, the situation with Xfwm is worse than I thought, since it completely breaks the DPI scaling that will be introduced in #548.

I think the simplest thing to do is to just have these methods no-op if you're running Xfwm. While it's not the most elegant thing, the only alternative is to add a scary notice to the docs and expose EventsLoopExt::get_wm_name, and I'm quite confident that only something like 1/16th of people would actually follow that proviso. Since Xfwm is my main WM, that's not a risk I'm willing to take.

I'll add that check myself, it's just I want to make sure there's agreement that it's reasonable. I'd also like to add some documentation stating that using these methods doesn't exempt one from handling Resized, since that event can still be triggered via DPI scaling, fullscreen mode, etc.

@dannyfritz
Copy link
Contributor Author

dannyfritz commented Jun 11, 2018

So I made it so it can go fullscreen and change the resizability of the restored window on Windows. I'm not particularly fond of the duplication of function in the restore function though. But it does seem to work as I would expect when swapping fullscreen and resizability.

I'll mention that when going from window to fullscreen and back to window, min and max window sizes are forgotten.

@francesca64
Copy link
Member

I'll mention that when going from window to fullscreen and back to window, min and max window sizes are forgotten.

I'm guessing it already had that problem (this isn't a regression)?

@dannyfritz
Copy link
Contributor Author

dannyfritz commented Jun 11, 2018

Oh, actually, it turns out I removed the min/max from my example and forgot it. So it is definitely remembering the min/max of the window. https://gist.github.com/dannyfritz/6eb8e7718b1cb3871e11fdefa32d0a14

But... the fullscreen is... interesting. It only gets to the size of the max dimensions.
2018-06-11_13-56-37

@dannyfritz
Copy link
Contributor Author

And testing the example without resizable code on master confirms it is not a regression. I don't see an issue for it in the issue tracker if this is indeed unintended.

@francesca64
Copy link
Member

It only gets to the size of the max dimensions.

What's supposed to happen here isn't well-defined, which is to say, no one's actually thought about it much. Though, I think we probably all expect setting a window to fullscreen to set it to fullscreen, so that should probably take precedence over the max size.

Maybe I'll remember to fix that when I rebase #548, since that also adds logic for determining when the window is entering fullscreen.

Anyway, thanks for all the work on this! We should be good to merge now, right after I make the changes I mentioned.

@dannyfritz
Copy link
Contributor Author

That's great to hear. 😄

You have been both very knowledgeable and helpful throughout the process.

@francesca64
Copy link
Member

Aw, thanks so much!

@francesca64 francesca64 merged commit be5a2b0 into rust-windowing:master Jun 11, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

3 participants